#ifndef WORLDEDITORAPP_H
#define WORLDEDITORAPP_H

#undef GENERATE_ENUM_STRINGS

#include "resource.h"
#include <LitEnumStr.h>
#include "TestEnum.h"

#include <QtGui/QMainWindow>
#include <LitResourcesList.h>
#include <LitFileSystem.h>

#include "RenderViewport.h"
#include "ProjectItemProperties.h"
#include "MovableMover.h"

#include "ui_worldeditorapp.h"
#include "EditorSettings.h"
#include "Project.h"
#include <LitPhysicsManager.h>
#include "PhysicsViewport.h"
#include "LitPhysicsManager.h"

#define EDT_TRY try
#define EDT_CATCH( parent_w ) catch( std::exception & e ){ QMessageBox::warning(parent_w, "Error", e.what()); }catch( ... ){ QMessageBox::warning(parent_w, "Error", "Unknown Error Happened !"); }
#define EDT_CATCH_MSG( parent_w, msg ) catch( std::exception & e ){ QMessageBox::warning(parent_w, "Error", e.what()); }catch( ... ){ QMessageBox::warning(parent_w, "Error", "Unknown Error Happened !\r\n"+QString(Lit::String(msg).cstr())); }
#define EDT_CATCH_RETHROW( parent_w ) catch( std::exception & e ){ QMessageBox::warning(parent_w, "Error", e.what()); throw; }catch( ... ){ QMessageBox::warning(parent_w, "Error", "Unknown Error Happened !")); throw; }

#define EXC_GUARD( parent, func, desc ) \
	try{ func; } \
	catch( std::exception & e ){ QMessageBox::warning( parent, desc, QString(e.what()) ); } \
	catch( ... ){ QMessageBox::warning( parent, desc, "Unknown error happened" ); }

#include "ui_physics_obj_creator.h"

class PhysicsObjectCreator : public QDialog
{
	Q_OBJECT
protected:
	Ui::PhysicsObjCreator ui;
	OgreWidget * mOgre;

protected slots:
	void changeShapeRotationAxis( const QString &str )
	{
		if( str == Lit::trAxisDirection( Lit::AXIS_X ) )
		{
		}
		else if( str == Lit::trAxisDirection( Lit::AXIS_X ) )
		{
		}
		else if( str == Lit::trAxisDirection( Lit::AXIS_X ) )
		{
		}
	}
	void changeShapeType( const QString &str )
	{
		if( str == Lit::Physics::trShapeType( Lit::Physics::ST_NULL ) )
		{
		}
		else if( str == Lit::Physics::trShapeType( Lit::Physics::ST_BOX ) )
		{
		}
		else if( str == Lit::Physics::trShapeType( Lit::Physics::ST_SPHERE ) )
		{
		}
		else if( str == Lit::Physics::trShapeType( Lit::Physics::ST_PLANE ) )
		{
		}
	}

public:
	PhysicsObjectCreator( OgreWidget * ogre, QWidget * parent ) : QDialog( parent ){ 
		ui.setupUi(this); 
		ui.previewContent->setOgreWidget( ogre );
		
		connect( ui.shapeType, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(changeShapeType(const QString &)) );
		connect( ui.shapeRotationAxis, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(changeShapeRotationAxis(const QString &)) );
	}
	~PhysicsObjectCreator( ){}
	
	int exec( const Lit::EntityPtr &getEntity ){ 
		ui.shapeType->clear();
		ui.shapeType->addItem( trShapeType( Lit::Physics::ST_NULL ) );
		ui.shapeType->addItem( trShapeType( Lit::Physics::ST_BOX ) );
		ui.shapeType->addItem( trShapeType( Lit::Physics::ST_SPHERE ) );
		ui.shapeType->addItem( trShapeType( Lit::Physics::ST_PLANE ) );
		
		ui.shapeRotationAngle->setValue(0);

		ui.shapeRotationAxis->clear();
		ui.shapeRotationAxis->addItem( Lit::trAxisDirection( Lit::AXIS_X ) );
		ui.shapeRotationAxis->addItem( Lit::trAxisDirection( Lit::AXIS_Y ) );
		ui.shapeRotationAxis->addItem( Lit::trAxisDirection( Lit::AXIS_Z ) );
		
		ui.shapeOffsetX->setText("0.0");
		ui.shapeOffsetY->setText("0.0");
		ui.shapeOffsetZ->setText("0.0");
		/*OgreSubWidget * subOgre = new OgreSubWidget( ui.previewContent );
		subOgre->setObjectName( "SubOgrePhysicsPreview" );
		subOgre->setOgreWidget( mOgre );*/
		ui.previewContent->createScene();
		ui.previewContent->replaceMesh( getEntity->getMeshName() );
		ui.previewContent->destroyScene();
		int ret = QDialog::exec(); 
		//delete subOgre, subOgre = NULL;
		return ret;
	}

};

class WorldEditorApp : public QMainWindow, public Ogre::LogListener, public OgreWidgetListener, public OgreSubWidgetListener
{
	Q_OBJECT
	
private:
	Ogre::Log*					mLog;
	Ui::WorldEditorAppClass		ui;
	std::map<std::string, bool> mCompositors;
	
	ProjectPtr					mProject;
	Lit::ResourcesListPtr		mResources;
	OgreWidget*					mOgre;
	RenderViewportPtr			mViewport;
	ProjectItemPreviewPtr		mPreview;
	ProjectItemPropertiesPtr	mProperties;
	Ogre::Real					mLastFrameTime;
	Lit::RefPtr<MovablePlacer>	mPlacer;
	Lit::RefPtr<EditorSettings> mSettings;
	
	Lit::Physics::WorldPtr	mWorld;
	PhysicsObjectCreator*			mPhysicsObjectCreator;
protected slots:
	void renderMousePress( QMouseEvent*evt );
	void renderMouseMove( QMouseEvent * evt );
	void renderMouseRelease( QMouseEvent * evt );

	void keyPressEvent( QKeyEvent*evt );
	void renderKeyRelease( QKeyEvent * evt );
	
	void actionMoveXZ(bool);
	void actionMoveXY(bool);
	void actionMoveYZ(bool);

public:
	WorldEditorApp(QWidget *parent = 0, Qt::WFlags flags = 0);
	~WorldEditorApp();
	
	bool frameRenderingQueued( const Ogre::FrameEvent &evt );


	void mouseDragging(  MouseDrag & drag  );
	void updateUi( );

	void listResources( );

	void createScene( );
	void destroyScene( );

    void messageLogged( const Ogre::String& message, Ogre::LogMessageLevel lml, bool maskDebug, const Ogre::String &logName );
	void createProject( const std::string &name = std::string() );
	void saveProjectAs( );
	void saveProject();
	void openProject();
	
	void activateMoveTool( bool state );
	void activateRotateTool( bool state );
	void activateScaleTool( bool state );

	protected slots:
		void on_actionMove_triggered(bool);
		void on_actionRotate_triggered(bool state);
		void on_actionScale_triggered(bool state);

		void on_actionVisual_Debugger_triggered( bool state );
		void on_actionAdd_To_Simulation_triggered(bool);
		void on_actionReset_triggered(bool);
		void on_actionRun_triggered(bool);
		void on_actionSettings_triggered(bool);

		void renderMenuRequested(float, float);
		void updateSceneSelection( const UserQueryResult& );

		void on_actionNew_Scene_triggered(bool);
		void on_actionOpen_Scene_triggered(bool);
		void on_actionSave_Scene_triggered(bool);
		void on_actionSave_Scene_As_triggered(bool);
		void on_actionClose_Scene_triggered(bool);
		void on_actionExit_triggered( bool );

		// Place items by double click
		void on_ModelList_itemDoubleClicked( QListWidgetItem * );
		void on_LightsList_itemDoubleClicked(QListWidgetItem*);

		// Preview items by changing selection
		void on_MaterialList_itemClicked( QListWidgetItem * sel );
		void on_ModelList_itemClicked( QListWidgetItem * sel );

		void on_CompositorEnable_clicked( bool );
};

#endif // MATERIALEDITORAPP_H
